#include "udp.h"

#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

static int
init_udp_client_(UdpClient* uc, const char* host, const char* port)
{
  memset(&uc->hints, 0, sizeof uc->hints);
  uc->hints.ai_family = AF_INET; // set to AF_INET to use IPv4
  uc->hints.ai_socktype = SOCK_DGRAM;

  int rv = 0;
  if ((rv = getaddrinfo(host, port, &uc->hints, &uc->servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return 1;
  }

  // loop through all the results and make a socket
  for (uc->p = uc->servinfo; uc->p != NULL; uc->p = uc->p->ai_next) {
    if ((uc->sockfd = socket(
           uc->p->ai_family, uc->p->ai_socktype, uc->p->ai_protocol)) == -1) {
      perror("talker: socket");
      continue;
    }

    break;
  }

  if (uc->p == NULL) {
    fprintf(stderr, "talker: failed to create socket\n");
    return 2;
  }
  return (0);
}

UdpClient*
init_udp_client(const char* addr, const char* port)
{
  UdpClient* uc = calloc(sizeof(UdpClient), 1);
  if (uc) {
    if (init_udp_client_(uc, addr, port)) {
      free(uc);
      return NULL;
    }
    return uc;
  }

  return NULL;
}

static int
udpc_send_message__(UdpClient* uc, const void* mem, int len)
{
  if (uc && uc->sockfd) {
    int result =
      sendto(uc->sockfd, mem, len, 0, uc->p->ai_addr, uc->p->ai_addrlen);

    if (result == -1) {
      perror("talker: sendto");
    }

    return result;
  }
  return (0);
}

int
udpc_send_message(UdpClient* uc, const char* msg)
{
  return udpc_send_message__(uc, msg, strlen(msg) + 1);
}

int
udpc_send_data(UdpClient* uc, const void* mem, uint16_t size)
{
  return udpc_send_message__(uc, mem, size);
}

void
close_udp_client(UdpClient* uc)
{
  if (uc && uc->sockfd) {
    if (uc->servinfo)
      freeaddrinfo(uc->servinfo);
    close(uc->sockfd);
    free(uc);
  }
}

int
test_main(void)
{
  UdpClient * uc = init_udp_client("127.0.0.1", "34567");
  for (int i = 0; i < 60; ++i) {
    udpc_send_message(uc, "abcdef");
    usleep(100000);
  }
  close_udp_client(uc);

  return (0);
}
